package com.lz.gmall.order.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import java.util.Date;
import java.math.BigDecimal;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lz.gamll.feign.cart.AddCartFeignClient;
import com.lz.gamll.feign.product.SkuDetailFeignClient;
import com.lz.gamll.feign.ware.WareFeignClient;
import com.lz.gmall.common.execption.GmallException;
import com.lz.gmall.common.result.ResultCodeEnum;
import com.lz.gmall.common.utils.UserAuthUtil;
import com.lz.gmall.constant.GmallConstant;
import com.lz.gmall.order.dto.DetailDTO;
import com.lz.gmall.order.dto.OrderSubmitDTO;
import com.lz.gmall.order.entity.*;
import com.lz.gmall.order.enums.OrderStatus;
import com.lz.gmall.order.enums.ProcessStatus;
import com.lz.gmall.order.mapper.OrderDetailMapper;
import com.lz.gmall.order.mapper.PaymentInfoMapper;
import com.lz.gmall.order.service.OrderDetailService;
import com.lz.gmall.order.service.OrderInfoService;
import com.lz.gmall.order.mapper.OrderInfoMapper;
import com.lz.gmall.order.service.OrderStatusLogService;
import com.lz.gmall.order.vo.OrderDetailListVo;
import com.lz.gmall.order.vo.WareSkuMapVo;
import com.lz.gmall.product.entity.SkuInfo;
import com.lz.gmall.rabbit.constant.RabbitConstant;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.stream.Collectors;

/**
 *
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo>
    implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private OrderStatusLogService orderStatusLogService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private SkuDetailFeignClient skuDetailFeignClient;

    @Autowired
    private AddCartFeignClient addCartFeignClient;

    @Autowired
    private WareFeignClient wareFeignClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private PaymentInfoMapper paymentInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    /**
     * 把订单中的数据存入数据库中，进行一系列的校验通过后存入数据库
     * @param tradeNo 订单号
     * @param orderSubmitDTO 订单中商品的数据
     * @return
     */
    @Override
    public String submitOrder(String tradeNo, OrderSubmitDTO orderSubmitDTO) {
        //先判断订单是否重复提交
        String script = "if redis.call(\"exists\",KEYS[1])\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        Long execute = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(GmallConstant.REDIS_ORDER_CONFIRM_KEY + tradeNo));
        if (execute == 0){
            //说明redis中没有该订单tradeNo，说明已经创建过订单
            throw new GmallException(ResultCodeEnum.REQ_REPEAT);
        }
        //价格校验
        List<DetailDTO> orderDetailList = orderSubmitDTO.getOrderDetailList();
        List<DetailDTO> detailDTOList = orderDetailList.stream().filter(detailDTO -> {
            SkuInfo skuInfo = skuDetailFeignClient.getSkuInfoPriceBySkuId(detailDTO.getSkuId()).getData();
            return skuInfo.getPrice().compareTo(detailDTO.getOrderPrice()) != 0;
        }).collect(Collectors.toList());
        if (detailDTOList.size()>0){
            throw new GmallException(ResultCodeEnum.SKU_PRICE_CHANGE) ;
        }

        //库存校验
        List<DetailDTO> stockList = orderDetailList.stream().filter(detailDTO -> {
            HashMap<String, String> map = new HashMap<>();
            map.put("skuId", detailDTO.getSkuId().toString());
            map.put("num", detailDTO.getSkuNum().toString());
            String body = wareFeignClient.hasStock(map).getBody();
            return "0".equalsIgnoreCase(body);
        }).collect(Collectors.toList());
        if (stockList.size()>0){
            throw new GmallException(ResultCodeEnum.SKU_STOCK_CHANGE);
        }

        //生成订单
        OrderInfo orderInfo = saveOrderInfo(tradeNo , orderSubmitDTO) ;

        // 保存订单明细
        saveOrderDetail(orderInfo , orderSubmitDTO);

        // 保存状态日志数据
        saveOrderStatusLog(orderInfo) ;

        //关单操作，30分钟没有支付进行关单操作
        Map<String,Object> map = new HashMap<>();
        //唯一标识
        map.put("orderId",orderInfo.getId());
        //分片键，携带上，提高效率
        map.put("userId",orderInfo.getUserId());
        //向rabbitmq中发送消息
        rabbitTemplate.convertAndSend(RabbitConstant.ORDER_EXCHANGE_NAME,RabbitConstant.ORDER_QUEUE_ROUTING_KEY_NAME, JSON.toJSONString(map));

        //删除购物车中选中的商品
        addCartFeignClient.deleteCheckedCartItem() ;

        return String.valueOf(orderInfo.getId());
    }

    /**
     * 支付超时之后，进入mq调用该方法进行关单操作
     * @param orderId 订单id
     * @param userId 用户id
     */
    @Override
    public void closeOrder(Long orderId, Long userId) {

        //进行关单之前先进行判断订单状态是否改变
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getId,orderId);
        wrapper.eq(OrderInfo::getUserId,userId);
        OrderInfo orderInfo = getOne(wrapper);
        //判断是否支付订单
        if (OrderStatus.UNPAID.name().equals(orderInfo.getOrderStatus()) &&  ProcessStatus.UNPAID.name().equals(orderInfo.getProcessStatus())){
            //未支付状态
            //修改为已关闭，这个时候用户可能支付了订单，乐观锁思想，修改的时候再进行条件判断（判断订单状态为未支付）
            LambdaQueryWrapper<OrderInfo> closeWrapper = new LambdaQueryWrapper<>();
            closeWrapper.eq(OrderInfo::getId,orderId);
            closeWrapper.eq(OrderInfo::getUserId,userId);
            closeWrapper.eq(OrderInfo::getOrderStatus,OrderStatus.UNPAID.name());
            closeWrapper.eq(OrderInfo::getProcessStatus,ProcessStatus.UNPAID.name());

            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            this.update(orderInfo,wrapper);
        }

    }

    /**
     * 修改订单的支付状态，支付宝支付成功之后，通过mq调用进行修改订单的状态
     * @param msg  支付成功之后，支付宝平台传来的订单数据
     */
    @Override
    public void updateOrderPayedStatus(String msg) {

        //插入支付记录
        PaymentInfo paymentInfo = getPaymentInfo(msg);
        paymentInfoMapper.insert(paymentInfo);

        //查询订单
        // 根据订单的id和用户的id查询订单数据
        LambdaQueryWrapper<OrderInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
        lambdaQueryWrapper.eq(OrderInfo::getId , paymentInfo.getOrderId()) ;
        lambdaQueryWrapper.eq(OrderInfo::getUserId , paymentInfo.getUserId()) ;
        OrderInfo orderInfo = this.getOne(lambdaQueryWrapper);

        //修改订单状态
        String orderStatus = orderInfo.getOrderStatus();
        String processStatus = orderInfo.getProcessStatus();

        //判断订单是否是未支付或者是以关闭，才修改订单的状态
        //两种方案：
        //第一种，直接修改为已支付
        //第二种：如果订单状态是已关闭，调用支付宝平台的退款接口进行退款操作
        if ((OrderStatus.UNPAID.name().equals(orderStatus) && ProcessStatus.UNPAID.name().equals(processStatus))
        || (OrderStatus.CLOSED.name().equals(orderStatus) && ProcessStatus.CLOSED.name().equals(processStatus))){

            // 更改订单的状态为已支付
            orderInfo.setOrderStatus(OrderStatus.PAID.name());
            orderInfo.setProcessStatus(ProcessStatus.PAID.name());
            lambdaQueryWrapper.in(OrderInfo::getOrderStatus , OrderStatus.UNPAID.name() , OrderStatus.CLOSED.name() ) ;
            lambdaQueryWrapper.in(OrderInfo::getProcessStatus , ProcessStatus.UNPAID.name() , ProcessStatus.CLOSED.name()) ;
            boolean update = this.update(orderInfo, lambdaQueryWrapper);
        }

        //订单支付完之后，向库存系统发送消息，进行减库存
        WareStockMsg wareStockMsg = getWareStockMsg(orderInfo);
        String result = JSON.toJSONString(wareStockMsg);
        rabbitTemplate.convertAndSend(RabbitConstant.EXCHANGE_DIRECT_WARE_STOCK,RabbitConstant.ROUTING_WARE_STOCK,result);
    }

    /**
     * 库存系统扣减完之后，发送消息到mq，order监听到之后，修改订单的状态（代发货）
     * ‘DEDUCTED’  (已减库存)
     * ‘OUT_OF_STOCK’  (库存超卖)
     * @param msg 库存系统发送的消息
     */
    @Override
    public void updateOrderStatusAfterWare(String msg) {
        WareStockResultMsg wareStockResultMsg = JSON.parseObject(msg, WareStockResultMsg.class);
        Long orderId = wareStockResultMsg.getOrderId();
        //没有用户id
        OrderInfo orderInfo = getById(orderId);
        String status = wareStockResultMsg.getStatus();
        //判断订单状态为已支付，才修改状态
        if (OrderStatus.PAID.name().equals(orderInfo.getOrderStatus())&&ProcessStatus.PAID.name().equals(orderInfo.getProcessStatus())){
            LambdaQueryWrapper<OrderInfo> orderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderInfoLambdaQueryWrapper.eq(OrderInfo::getId,orderId);
            orderInfoLambdaQueryWrapper.eq(OrderInfo::getUserId,orderInfo.getUserId());
            orderInfoLambdaQueryWrapper.eq(OrderInfo::getOrderStatus,OrderStatus.PAID.name());
            orderInfoLambdaQueryWrapper.eq(OrderInfo::getProcessStatus,ProcessStatus.PAID.name());
            switch (status){
                case "DEDUCTED":
                    orderInfo.setOrderStatus(OrderStatus.WAITING_DELEVER.name());
                    orderInfo.setProcessStatus(ProcessStatus.NOTIFIED_WARE.name());
                    break;
                case "OUT_OF_STOCK":
                    orderInfo.setOrderStatus(OrderStatus.WAITING_SCHEDULE.name());
                    orderInfo.setProcessStatus(ProcessStatus.STOCK_EXCEPTION.name());
                    break;
                default:
                    throw new GmallException(ResultCodeEnum.WARE_ERROR);
            }
            update(orderInfo,orderInfoLambdaQueryWrapper);
        }
    }

    /**
     *订单在支付之后进行拆单操作
     * @param orderId 订单id
     * @param wareSkuMap 仓库编号与商品的对照关系
     *                   例如 ：[{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
     *                  表示：sku为2号，10号的商品在1号仓库
     *                      sku为3号，10号的商品在2号仓库
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<WareStockMsg> orderSplit(Long orderId, String wareSkuMap) {
        List<WareSkuMapVo> wareSkuMapVos = JSON.parseArray(wareSkuMap, WareSkuMapVo.class);
        LambdaQueryWrapper<OrderInfo> orderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderInfoLambdaQueryWrapper.eq(OrderInfo::getId,orderId);
        OrderInfo oldOrderInfo = getOne(orderInfoLambdaQueryWrapper);

        List<WareStockMsg> wareStockMsgList = new ArrayList<>();

        for (WareSkuMapVo wareSkuMapVo : wareSkuMapVos) {
            //创建新的订单
            OrderInfo newOrderInfo = new OrderInfo();
            newOrderInfo.setConsignee(oldOrderInfo.getConsignee());
            newOrderInfo.setConsigneeTel(oldOrderInfo.getConsigneeTel());

            //查取订单详情，获取不同库存下的订单商品的总金额
            List<Long> skuIds = wareSkuMapVo.getSkuIds();
            LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId,oldOrderInfo.getId());
            orderDetailLambdaQueryWrapper.eq(OrderDetail::getUserId,oldOrderInfo.getUserId());
            orderDetailLambdaQueryWrapper.in(OrderDetail::getSkuId,skuIds);
            List<OrderDetail> orderDetailList = orderDetailMapper.selectList(orderDetailLambdaQueryWrapper);
            BigDecimal totalAmount = orderDetailList.stream().map(orderDetail -> orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum())))
                    .reduce(BigDecimal::add).get();

            newOrderInfo.setTotalAmount(totalAmount);
            newOrderInfo.setOrderStatus(oldOrderInfo.getOrderStatus());
            newOrderInfo.setUserId(oldOrderInfo.getUserId());
            newOrderInfo.setPaymentWay(oldOrderInfo.getPaymentWay());
            newOrderInfo.setDeliveryAddress(oldOrderInfo.getDeliveryAddress());
            newOrderInfo.setOrderComment(oldOrderInfo.getOrderComment());
            newOrderInfo.setOutTradeNo(oldOrderInfo.getOutTradeNo());
            newOrderInfo.setTradeBody(oldOrderInfo.getTradeBody());
            newOrderInfo.setCreateTime(new Date());
            newOrderInfo.setExpireTime(oldOrderInfo.getExpireTime());
            newOrderInfo.setProcessStatus(oldOrderInfo.getProcessStatus());
            newOrderInfo.setTrackingNo(""); //物流单号
            newOrderInfo.setParentOrderId(orderId);
            newOrderInfo.setImgUrl(orderDetailList.get(0).getImgUrl());


            newOrderInfo.setProvinceId(0L);
            newOrderInfo.setOperateTime(new Date());
            newOrderInfo.setActivityReduceAmount(new BigDecimal("0"));
            newOrderInfo.setCouponAmount(new BigDecimal("0"));
            newOrderInfo.setOriginalTotalAmount(new BigDecimal("0"));
            newOrderInfo.setFeightFee(new BigDecimal("0"));
            newOrderInfo.setRefundableTime(new Date());

            orderInfoMapper.insert(newOrderInfo);

            //添加商品详情
            for (OrderDetail oldOrderDetail : orderDetailList) {
                OrderDetail newOrderDetail = new OrderDetail();
                BeanUtils.copyProperties(oldOrderDetail,newOrderDetail);
                newOrderDetail.setId(null);
                newOrderDetail.setOrderId(newOrderInfo.getId());
                orderDetailMapper.insert(newOrderDetail);
            }
            //构建返回参数
            WareStockMsg wareStockMsg = new WareStockMsg();

            wareStockMsg.setOrderId(newOrderInfo.getId());
            wareStockMsg.setConsignee(newOrderInfo.getConsignee());
            wareStockMsg.setConsigneeTel(newOrderInfo.getConsigneeTel());
            wareStockMsg.setOrderComment(newOrderInfo.getOrderComment());
            wareStockMsg.setOrderBody(newOrderInfo.getTradeBody());
            wareStockMsg.setDeliveryAddress(newOrderInfo.getDeliveryAddress());
            wareStockMsg.setPaymentWay("2");
            wareStockMsg.setWareId(wareSkuMapVo.getWareId());

            List<Sku> skuList = orderDetailList.stream().map(orderDetail -> {
                Sku sku = new Sku();
                sku.setSkuId(orderDetail.getSkuId());
                sku.setSkuNum(Long.parseLong(orderDetail.getSkuNum()));
                sku.setSkuName(orderDetail.getSkuName());
                return sku;
            }).collect(Collectors.toList());
            wareStockMsg.setDetails(skuList);
            wareStockMsgList.add(wareStockMsg);
        }

        //修改之前的订单状态为已拆单,判断订单状态为以及支付
        if (OrderStatus.PAID.name().equals(oldOrderInfo.getOrderStatus()) && ProcessStatus.PAID.name().equals(oldOrderInfo.getProcessStatus())){

            oldOrderInfo.setOrderStatus(OrderStatus.SPLIT.name());
            oldOrderInfo.setProcessStatus(ProcessStatus.SPLIT.name());

            orderInfoLambdaQueryWrapper.eq(OrderInfo::getUserId,oldOrderInfo.getUserId());
            orderInfoLambdaQueryWrapper.eq(OrderInfo::getOrderStatus , OrderStatus.PAID.name()) ;
            orderInfoLambdaQueryWrapper.eq(OrderInfo::getProcessStatus , ProcessStatus.PAID.name()) ;
            orderInfoMapper.update(oldOrderInfo,orderInfoLambdaQueryWrapper);
        }

        return wareStockMsgList;
    }

    /**
     * 获取所有分表后的小订单
     * @param pageNum 页码
     * @param limit 页数
     * @return
     */
    @Override
    public Page getOrderPageList(Integer pageNum, Integer limit) {

        Page orderInfoPage = new Page<>(pageNum,limit);

        LambdaQueryWrapper<OrderInfo> orderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderInfoLambdaQueryWrapper.ne(OrderInfo::getOrderStatus,OrderStatus.SPLIT.name());
        orderInfoLambdaQueryWrapper.ne(OrderInfo::getProcessStatus,ProcessStatus.SPLIT.name());

        orderInfoMapper.selectPage(orderInfoPage, orderInfoLambdaQueryWrapper);

        List orderInfoList = orderInfoPage.getRecords();

        List<OrderDetailListVo> orderDetailListVoList = new ArrayList<>();

        for (Object orderInfoObj : orderInfoList) {

            OrderInfo orderInfo = JSON.parseObject(JSON.toJSONString(orderInfoObj), OrderInfo.class);

            LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId,orderInfo.getId());
            orderDetailLambdaQueryWrapper.eq(OrderDetail::getUserId,orderInfo.getUserId());
            List<OrderDetail> orderDetailList = orderDetailMapper.selectList(orderDetailLambdaQueryWrapper);

            OrderDetailListVo orderDetailListVo = new OrderDetailListVo();
            orderDetailListVo.setOrderId(orderInfo.getId());
            orderDetailListVo.setCreateTime(orderInfo.getCreateTime());
            orderDetailListVo.setTotalAmount(orderInfo.getTotalAmount());
            orderDetailListVo.setOrderDetailList(orderDetailList);
            orderDetailListVoList.add(orderDetailListVo);
        }

        orderInfoPage.setRecords(orderDetailListVoList);
        return orderInfoPage;
    }


    /**
     * 将订单状态修改为已支付，向库存系统进行减库存操作，需要向库存系统传递的参数
     * @param orderInfo 订单数据
     * @return
     */
    private WareStockMsg getWareStockMsg(OrderInfo orderInfo) {
        WareStockMsg wareStockMsg = new WareStockMsg();
        wareStockMsg.setOrderId(orderInfo.getId());
        wareStockMsg.setConsignee(orderInfo.getConsignee());
        wareStockMsg.setConsigneeTel(orderInfo.getConsigneeTel());
        wareStockMsg.setOrderComment(orderInfo.getOrderComment());
        wareStockMsg.setOrderBody(orderInfo.getTradeBody());
        wareStockMsg.setDeliveryAddress(orderInfo.getDeliveryAddress());

        //查询订单详情
        LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId,orderInfo.getId());
        orderDetailLambdaQueryWrapper.eq(OrderDetail::getUserId,orderInfo.getUserId());
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(orderDetailLambdaQueryWrapper);
        List<Sku> skuList = orderDetailList.stream().map(orderDetail -> {
            Sku sku = new Sku();
            sku.setSkuId(orderDetail.getSkuId());
            sku.setSkuNum(Long.valueOf(orderDetail.getSkuNum()));
            sku.setSkuName(orderDetail.getSkuName());
            return sku;
        }).collect(Collectors.toList());
        wareStockMsg.setDetails(skuList);

        return wareStockMsg;
    }

    /**
     * 要将支付记录加入数据库，根据支付宝前台传来的数据构建支付详情类
     * @param msg 支付成功之后，支付宝平台传来的订单数据
     * @return
     */
    private PaymentInfo getPaymentInfo(String msg) {
        PaymentInfo paymentInfo = new PaymentInfo();

        Map map = JSON.parseObject(msg, Map.class);
        String outTradeNo = map.get("out_trade_no").toString();
        LambdaQueryWrapper<OrderInfo> orderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderInfoLambdaQueryWrapper.eq(OrderInfo::getOutTradeNo,outTradeNo);
        OrderInfo orderInfo = this.getOne(orderInfoLambdaQueryWrapper);

        paymentInfo.setUserId(orderInfo.getUserId());
        paymentInfo.setOutTradeNo(orderInfo.getOutTradeNo());
        paymentInfo.setOrderId(String.valueOf(orderInfo.getId()));
        paymentInfo.setPaymentType("ALIPAY");

        String tradeNo = map.get("trade_no").toString();
        paymentInfo.setTradeNo(tradeNo);

        paymentInfo.setTotalAmount(orderInfo.getTotalAmount());
        paymentInfo.setSubject(orderInfo.getTradeBody());
        paymentInfo.setPaymentStatus(OrderStatus.PAID.name());
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setCallbackContent(JSON.toJSONString(map));

        return paymentInfo;
    }

    /**
     * 提交订单，保存状态日志数据
     * @param orderInfo 订单数据
     */
    private void saveOrderStatusLog(OrderInfo orderInfo) {
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setUserId(orderInfo.getUserId());
        orderStatusLog.setOrderId(orderInfo.getId());
        orderStatusLog.setOrderStatus(orderInfo.getOrderStatus());
        //操作时间
        orderStatusLog.setOperateTime(new Date());

        orderStatusLogService.save(orderStatusLog);
    }

    /**
     * 提交订单，保存订单明细
     * @param orderInfo   订单数据
     * @param orderSubmitDTO  页面传过来的提交订单
     */
    private void saveOrderDetail(OrderInfo orderInfo, OrderSubmitDTO orderSubmitDTO) {

        List<DetailDTO> orderDetailList = orderSubmitDTO.getOrderDetailList();
        List<OrderDetail> detailList = orderDetailList.stream().map(detailDTO -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setUserId(orderInfo.getUserId());
            orderDetail.setOrderId(orderInfo.getId());
            orderDetail.setSkuId(detailDTO.getSkuId());
            orderDetail.setSkuName(detailDTO.getSkuName());
            orderDetail.setImgUrl(detailDTO.getImgUrl());
            orderDetail.setOrderPrice(detailDTO.getOrderPrice());
            orderDetail.setSkuNum(String.valueOf(detailDTO.getSkuNum()));
            orderDetail.setCreateTime(new Date());
            orderDetail.setSplitTotalAmount(detailDTO.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum())));
            orderDetail.setSplitActivityAmount(new BigDecimal("0"));
            orderDetail.setSplitCouponAmount(new BigDecimal("0"));
            return orderDetail;
        }).collect(Collectors.toList());

        orderDetailService.saveBatch(detailList);
    }

    /**
     * 根据前端提交的订单数据，生成订单
     * @param tradeNo  订单号
     * @param orderSubmitDTO  前端的传来的订单数据
     * @return
     */
    private OrderInfo saveOrderInfo(String tradeNo, OrderSubmitDTO orderSubmitDTO) {

        OrderInfo orderInfo = new OrderInfo();
        //收货人
        orderInfo.setConsignee(orderSubmitDTO.getConsignee());
        //收货人电话号码
        orderInfo.setConsigneeTel(orderSubmitDTO.getConsigneeTel());

        List<DetailDTO> orderDetailList = orderSubmitDTO.getOrderDetailList();
        BigDecimal totalAmount = orderDetailList.stream().map(detailDTO -> {
            return detailDTO.getOrderPrice().multiply(new BigDecimal(detailDTO.getSkuNum()));
        }).reduce(BigDecimal::add).get();
        //订单总金额
        orderInfo.setTotalAmount(totalAmount);
        //订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());

        String userId = UserAuthUtil.getUserAuthInfo().getUserId();
        //用户id
        orderInfo.setUserId(Long.parseLong(userId));
        //支付方式
        orderInfo.setPaymentWay(orderSubmitDTO.getPaymentWay());
        //收货人地址
        orderInfo.setDeliveryAddress(orderSubmitDTO.getDeliveryAddress());
        //订单备注
        orderInfo.setOrderComment(orderSubmitDTO.getOrderComment());
        //订单号
        orderInfo.setOutTradeNo(tradeNo);

        //订单体【默认用订单中第一个商品的名字即可】
        DetailDTO detailDTO = orderSubmitDTO.getOrderDetailList().get(0);
        orderInfo.setTradeBody(detailDTO.getSkuName());
        //创建时间
        orderInfo.setCreateTime(new Date());
        // 过期时间
        long time = System.currentTimeMillis() + RabbitConstant.ORDER_QUEUE_TTL ;
        orderInfo.setExpireTime(new Date(time));

        //订单的处理状态：一个订单状态对应多个处理状态，是一种更加详细的状态，给管理员查看
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());

        //物流编号
        //orderInfo.setTrackingNo("");

        //父订单id，后期进行拆单的时候使用父订单
        //orderInfo.setParentOrderId(0L);

        //使用第一个商品的图片作为订单图片
        orderInfo.setImgUrl(detailDTO.getImgUrl());

        //省id
        //orderInfo.setProvinceId(0L);

        //操作时间
        orderInfo.setOperateTime(new Date());
        //优惠活动以及优惠券金额
        orderInfo.setActivityReduceAmount(new BigDecimal("0"));
        orderInfo.setCouponAmount(new BigDecimal("0"));
        //原始金额
        orderInfo.setOriginalTotalAmount(totalAmount);
        //运费
        orderInfo.setFeightFee(new BigDecimal("0"));

        // 可退款日期（签收后30天）
        //orderInfo.setRefundableTime(new Date());

        //保存到数据库
        orderInfoMapper.insert(orderInfo);

        return orderInfo;
    }
}




